import type { UseFetchOptions } from 'nuxt/app'
import type { NitroFetchRequest, NitroFetchOptions } from 'nitropack'
import { useUserStore } from '~/stores/user'

// interface CustomOptions<R extends NitroFetchRequest> extends NitroFetchOptions<R> {
//   ignoreError?: boolean
//   retry?: number
// }

// interface CustomError {
//   message: string
//   statusCode: number
// }

export interface MyBaseResponse<T> {
  status: number
  message: string
  data?: T
}

const getMyRequestBaseUrl = (): string => {
  const config = useRuntimeConfig()
  const baseURL = import.meta.server ? config.apiServerBase : config.public.apiBase
  console.log('baseURL', import.meta.server, baseURL)
  return baseURL
}

function getMyRequestOptions<T, useFetch = false>(
  opt: useFetch extends true ? UseFetchOptions<T> : NitroFetchOptions<NitroFetchRequest>
): useFetch extends true ? UseFetchOptions<T> : NitroFetchOptions<NitroFetchRequest> {
  return {
    baseURL: getMyRequestBaseUrl(),
    retry: 0,
    timeout: 15 * 1000,
    onRequestError: res => {
      const { error } = res
      console.log('onRequestError', error)
    },
    onRequest(res) {
      const { options } = res
      if (opt.onRequest) {
        if (typeof opt.onRequest === 'function') {
          opt.onRequest(res)
        } else if (Array.isArray(opt.onRequest)) {
          opt.onRequest.forEach(hook => {
            if (typeof hook === 'function') {
              hook(res)
            }
          })
        }
      }

      options.headers.set('AI-Api-Version', 'v0.0.1')
      options.headers.set('AI-Api-OpenHost', 'ai.aiiiin.college')
      const userStore = useUserStore()
      // const token = getToken()
      const token = userStore.token
      // console.log('onRequest', request, token)
      if (token) {
        options.headers.set('Authorization', `Bearer ${token}`)
      }
    },
    onResponseError: res => {
      const { error } = res
      console.log('onResponseError', error, res)
    },
    onResponse: res => {
      if (opt.onResponse) {
        if (typeof opt.onResponse === 'function') {
          opt.onResponse(res)
        } else if (Array.isArray(opt.onResponse)) {
          opt.onResponse.forEach(hook => {
            if (typeof hook === 'function') {
              hook(res)
            }
          })
        }
      }

      const { response } = res
      const { _data } = response
      if (_data.status === 405 || _data.status === 409) {
        // 退出登录
        // logout()
        // showLogin()
      } else if (import.meta.client) {
        let errorCode
        if (!_data) {
          errorCode = response.status
        } else if (_data.status !== 200) {
          errorCode = _data.status
        }
        if (errorCode) {
          // showMessage(errorTip(errorCode))
        }
      }
    },
    ...opt
  }
}

export const errorTip = (status: number): string => {
  switch (status) {
    case 400:
      return '请求失败！请您稍后重试'
      break
    case 401:
      return '没有权限'
      break
    case 403:
      return '用户账号或者密码错误'
      break
    case 404:
      return '你所访问的资源不存在！'
      break
    case 405:
      return '未登录或者登录失效，请先登录'
      break
    case 408:
      return '请求超时！请您稍后重试'
      break
    case 409:
      return '检测到您的账号异地登录，请重新登录'
      break
    case 500:
      return '服务异常！'
      break
    case 502:
      return '网关错误！'
      break
    case 503:
      return '服务不可用！'
      break
    case 504:
      return '网关超时！'
      break
    default:
      return '请求失败！'
  }
}

export function $useMyRequest<T>(
  url: NitroFetchRequest,
  opt?: NitroFetchOptions<NitroFetchRequest>
) {
  const options = getMyRequestOptions<NitroFetchOptions<NitroFetchRequest>>(
    opt as NitroFetchOptions<NitroFetchRequest>
  )
  return $fetch<T>(url, options)
}

export function useMyRequest<T>(
  url: Ref<NitroFetchRequest> | NitroFetchRequest | (() => NitroFetchRequest), // Ref<ReqT> | ReqT | (() => ReqT)
  opt?: UseFetchOptions<T> // UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, ReqT, Method>
) {
  const options = getMyRequestOptions<T, true>(opt as UseFetchOptions<T>)
  return useFetch(url, options)
}
